﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Net;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;


public static class HttpHelper
{
    public static HttpWebRequest GetRequest(this string url, string method)
    {
        HttpWebRequest req = null;
        url = url.ToLower();
        if (url.Contains("https://") && url.IndexOf("https://") == 0)
        {
            ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
            req = (HttpWebRequest)WebRequest.CreateDefault(new Uri(url));
        }
        else
        {
            req = (HttpWebRequest)WebRequest.Create(url);
        }

        req.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36 MicroMessenger/7.0.4.501 NetType/WIFI MiniProgramEnv/Windows WindowsWechat";
        req.Method = method;
        req.KeepAlive = true;

        return req;
    }
    public static string Request(this string url, string method, bool isZip = false)
    {
        HttpWebRequest req = url.GetRequest(method);
        try
        {
            if (!isZip)
            {
                using (HttpWebResponse response = (HttpWebResponse)req.GetResponse())
                {
                    using (Stream myResponseStream = response.GetResponseStream())
                    {
                        using (StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.UTF8))
                        {
                            string ret = myStreamReader.ReadToEnd();
                            return ret;
                        }
                    }
                }
            }
            else
            {
                string ret = "";
                using (HttpWebResponse response = (HttpWebResponse)req.GetResponse())
                {
                    //获取目标网站的编码格式
                    string contentype = response.Headers["Content-Type"];
                    Regex regex = new Regex("charset\\s*=\\s*[\\W]?\\s*([\\w-]+)", RegexOptions.IgnoreCase);
                    if (response.ContentEncoding != null && response.ContentEncoding.ToLower() == "gzip")//如果使用了GZip则先解压
                    {
                        using (System.IO.Stream streamReceive = response.GetResponseStream())
                        {
                            using (var zipStream = new System.IO.Compression.GZipStream(streamReceive, System.IO.Compression.CompressionMode.Decompress))
                            {
                                //匹配编码格式
                                if (regex.IsMatch(contentype))
                                {
                                    Encoding ending = Encoding.GetEncoding(regex.Match(contentype).Groups[1].Value.Trim());
                                    using (StreamReader sr = new System.IO.StreamReader(zipStream, ending))
                                    {
                                        ret = sr.ReadToEnd();
                                    }
                                }
                                else
                                {
                                    using (StreamReader sr = new System.IO.StreamReader(zipStream, Encoding.UTF8))
                                    {
                                        ret = sr.ReadToEnd();
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        using (System.IO.Stream streamReceive = response.GetResponseStream())
                        {
                            using (System.IO.StreamReader sr = new System.IO.StreamReader(streamReceive, Encoding.Default))
                            {
                                ret = sr.ReadToEnd();
                            }
                        }
                    }
                    return ret;
                }
            }
        }
        catch (Exception ex)
        {
            //Log.Error("HttpHelper.Request(this string url, string method)", ex.Message + "\r\n错误源：\r\n" + ex.StackTrace);
            return null;
        }
    }
    public static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
    {
        return true;
    }
    public static HttpWebRequest GetRequest(this string url, string method, Dictionary<string, string[]> header)
    {
        HttpWebRequest req = null;
        url = url.ToLower();
        if (url.Contains("https://") && url.IndexOf("https://") == 0)
        {
            ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
            req = (HttpWebRequest)WebRequest.CreateDefault(new Uri(url));
        }
        else
        {
            req = (HttpWebRequest)WebRequest.Create(url);
        }
        req.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36 MicroMessenger/7.0.4.501 NetType/WIFI MiniProgramEnv/Windows WindowsWechat";

        req.Method = method;
        req.KeepAlive = true;
        if (header != null)
        {
            foreach (string key in header.Keys)
            {
                string kind = ((string[])header[key])[0];
                string value = ((string[])header[key])[1];
                if (kind == "Set") req.Headers.Add(key, value);
                else
                {
                    switch (key.ToLower())
                    {
                        case "contenttype": req.ContentType = value; break;
                        case "accept": req.Accept = value; break;
                        case "referer": req.Referer = value; break;
                        case "user-agent": req.UserAgent = value; break;
                    }
                }
            }
        }
        return req;
    }
    public static string Request(this string url, string method, Dictionary<string, string[]> header, bool isZip = true)
    {
        HttpWebRequest req = url.GetRequest(method, header);
        try
        {
            string ret = "";

            using (HttpWebResponse response = (HttpWebResponse)req.GetResponse())
            {
                //获取目标网站的编码格式
                string contentype = response.Headers["Content-Type"];
                Regex regex = new Regex("charset\\s*=\\s*[\\W]?\\s*([\\w-]+)", RegexOptions.IgnoreCase);
                if (response.ContentEncoding != null && response.ContentEncoding.ToLower() == "gzip")//如果使用了GZip则先解压
                {
                    using (System.IO.Stream streamReceive = response.GetResponseStream())
                    {
                        using (var zipStream = new System.IO.Compression.GZipStream(streamReceive, System.IO.Compression.CompressionMode.Decompress))
                        {
                            //匹配编码格式
                            if (regex.IsMatch(contentype))
                            {
                                Encoding ending = url.GetEncoding();// Encoding.GetEncoding(regex.Match(contentype).Groups[1].Value.Trim());
                                using (StreamReader sr = new System.IO.StreamReader(zipStream, ending))
                                {
                                    ret = sr.ReadToEnd();
                                }
                            }
                            else
                            {
                                Encoding encode = url.GetEncoding();
                                using (StreamReader sr = new System.IO.StreamReader(zipStream, encode)) // Encoding.UTF8))
                                {
                                    ret = sr.ReadToEnd();
                                }
                            }
                        }
                    }
                }
                else
                {
                    using (Stream streamReceive = response.GetResponseStream())
                    {
                        Encoding encode = url.GetEncoding();
                        using (StreamReader sr = new StreamReader(streamReceive, encode)) // Encoding.UTF8)) // Encoding.Default))
                        {
                            ret = sr.ReadToEnd();
                        }
                    }
                }
                return ret;
            }
        }
        catch (Exception ex)
        {
            return null;
        }
    }

    public static Encoding GetEncoding(this string strurl)
    {
        string urlToCrawl = strurl;
        if (urlToCrawl != null && urlToCrawl != "")
        {
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(urlToCrawl);
            //use GET method to get url's html
            req.Method = "GET";
            req.Accept = "*/*";
            req.Headers.Add("Accept-Language", "zh-cn,en-us;q=0.5");
            req.ContentType = "text/xml";
            //use request to get response
            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
            Encoding enc;
            try
            {
                if (resp.CharacterSet != "ISO-8859-1")
                    enc = Encoding.GetEncoding(resp.CharacterSet);
                else
                    enc = Encoding.UTF8;
            }
            catch
            {
                // *** Invalid encoding passed
                enc = Encoding.UTF8;
            }
            string sHTML = string.Empty;
            using (StreamReader read = new StreamReader(resp.GetResponseStream(), enc))
            {
                sHTML = read.ReadToEnd();
                Match charSetMatch = Regex.Match(sHTML, "charset=(?<code>[a-zA-Z0-9\\-]+)", RegexOptions.IgnoreCase);
                //string sChartSet = charSetMatch.Groups["code"].Value;
                string sChartSet = charSetMatch.Groups["0"].Value;
                //if it's not utf-8,we should redecode the html.
                if (!string.IsNullOrEmpty(sChartSet) && !sChartSet.Equals("utf-8", StringComparison.OrdinalIgnoreCase))
                {
                    sChartSet = sChartSet.ToLower().Trim().Replace(" ", "").Replace("charset=", "");
                    enc = Encoding.GetEncoding(sChartSet);
                }
            }
            return enc;
        }
        return Encoding.Default;
    }

    public static string Post(this string url, string data, Dictionary<string, string[]> headers)
    {
        //Dictionary<string, string[]> headers = new Dictionary<string, string[]>();

        HttpWebRequest req = null;
        url = url.ToLower();
        if (url.Contains("https://") && url.IndexOf("https://") == 0)
        {
            ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
            req = (HttpWebRequest)WebRequest.CreateDefault(new Uri(url));
        }
        else
        {
            req = (HttpWebRequest)WebRequest.Create(url);
        }
        if (headers != null && headers.Keys.Contains("UserAgent")) req.UserAgent = headers["UserAgent"][0];
        else req.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36 MicroMessenger/7.0.4.501 NetType/WIFI MiniProgramEnv/Windows WindowsWechat";
        if (headers != null)
        {
            foreach (string key in headers.Keys)
            {
                string kind = ((string[])headers[key])[0];
                string value = ((string[])headers[key])[1];
                if (kind == "Set") req.Headers.Add(key, value);
                else
                {
                    switch (key.ToLower())
                    {
                        case "contenttype": req.ContentType = value; break;
                        case "accept": req.Accept = value; break;
                        case "referer": req.Referer = value; break;
                        case "user-agent": req.UserAgent = value; break;
                    }
                }
            }
        }
        req.KeepAlive = true;
        req.Method = "POST";
        //req.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";

        if (!string.IsNullOrWhiteSpace(data))
        {
            byte[] postData = Encoding.UTF8.GetBytes(data);
            req.ContentLength = postData.Length;

            using (var postStream = req.GetRequestStream())
            {
                postStream.Write(postData, 0, postData.Length);
            }
        }
        using (var response = (HttpWebResponse)req.GetResponse())
        {
            using (Stream stream = response.GetResponseStream())
            {
                using (StreamReader reader = new StreamReader(stream, Encoding.GetEncoding("UTF-8")))
                {
                    string ret = reader.ReadToEnd();
                    return ret;
                }
            }
        }
    }

    public static string Post(this string url, string data, Dictionary<string, string[]> headers, Encoding encoding)
    {
        //Dictionary<string, string[]> headers = new Dictionary<string, string[]>();

        HttpWebRequest req = null;
        url = url.ToLower();
        if (url.Contains("https://") && url.IndexOf("https://") == 0)
        {
            ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
            req = (HttpWebRequest)WebRequest.CreateDefault(new Uri(url));
        }
        else
        {
            req = (HttpWebRequest)WebRequest.Create(url);
        }
        if (headers != null && headers.Keys.Contains("UserAgent")) req.UserAgent = headers["UserAgent"][0];
        if (headers != null)
        {
            foreach (string key in headers.Keys)
            {
                string kind = ((string[])headers[key])[0];
                string value = ((string[])headers[key])[1];
                if (kind == "Set") req.Headers.Add(key, value);
                else
                {
                    switch (key.ToLower())
                    {
                        case "contenttype": req.ContentType = value; break;
                        case "accept": req.Accept = value; break;
                        case "referer": req.Referer = value; break;
                        case "user-agent": req.UserAgent = value; break;
                    }
                }
            }
        }
        req.KeepAlive = true;
        req.Method = "POST";
        
        if (!string.IsNullOrWhiteSpace(data))
        {
            byte[] postData = encoding.GetBytes(data);// Encoding.UTF8.GetBytes(data);
            req.ContentLength = postData.Length;

            using (var postStream = req.GetRequestStream())
            {
                postStream.Write(postData, 0, postData.Length);
            }
        }
        using (var response = (HttpWebResponse)req.GetResponse())
        {
            using (Stream stream = response.GetResponseStream())
            {
                using (StreamReader reader = new StreamReader(stream, encoding)) // Encoding.GetEncoding("UTF-8")))
                {
                    string ret = reader.ReadToEnd();
                    return ret;
                }
            }
        }
    }
}
